<?php

/**
 *  商品库存
 */

namespace app\admin\service;
use app\facade\Basic;
use app\admin\model\Inventory as InventoryModel;
use think\facade\Db;

class ProductInventory extends BaseService
{
    /**
     *   获取 商品库存信息
     *   array $condition；
     *
     *   ===== 输入 =====
          * [
              * [
                  * 'productid' => '商品ID',
                  * 'wid' => '仓库',
                  * 'arrival_date' => Null,
                  * 'is_futures' => '0',
                  * 'quantity' => 5,
              * ]...
          * ];
     *
     * @action =  purchase 下单  delivery 发货
     *    ===== 输出  =====
 */

    public function inventory(array $condition , string  $action = 'purchase')
    {
        /* 判空 */
        if ( empty($condition) ) {
            return Basic::data(1,'库存参数不存在');
        }

        $Inventory = InventoryModel::field('id');
        foreach ($condition as $key => $value){

            $where = [];
            $field = 'id,productid,wid,arrival_date,is_futures,available_qty,is_sale,lock_qty,allow_zero_stock_sale,purchase_currency,purchase_price'.",{$value['wid']} as wid";

            if (!is_numeric($value['productid'])) {
                return Basic::data(1, 'KEY:'.$key.' productid 参数错误');
            }

            if (!is_numeric($value['wid'])) {
                return Basic::data(1, 'KEY:'.$key.' wid 参数错误');
            }

            if (!is_numeric($value['quantity']) ||  $value['quantity'] <= 0) {
                return Basic::data(1, 'KEY:'.$key.' quantity 参数错误');
            }

            if (!in_array($value['is_futures'], [0,1,2])) {
                return Basic::data(1, 'KEY:'.$key.' is_futures 参数错误');
            }

            $pay_quantity[implode('_', [
                $value['productid'],
                $value['wid'],
                $value['arrival_date'],
                $value['is_futures']
            ])] = $value['quantity'];

            /* 默认条件 */
            $where[] = ['is_del', '=', 0];
            $where[] = ['productid', '=', $value['productid']];
            $where[] = ['arrival_date', '=', is_null($value['arrival_date']) ? null : $value['arrival_date']];


            switch($action) {
                case 'purchase':
                    $where[] = ['is_futures', '=', $value['is_futures']];
                    $where[] = ['is_sale', '=', 1];
                    break;
                case 'delivery':
                    if ($value['is_futures'] != 0) {
                        return Basic::data(1, 'KEY:'.$key.' is_futures 只能发现货');
                    }
                    $where[] = ['is_futures', '=', 0];
                    $where[] = ['available_qty', 'exp', Db::raw('>= lock_qty')];
                    break;
                default:
                    return Basic::data(1,' Action 方法错误');
            }

            if ( $key == 0 ) {
                $Inventory->field($field)->where($where)->where(function ($query) use ($action) {
                        switch ($action) {
                            case 'purchase':
                                $query->where(function ($query) {
                                    $query->where('available_qty','>',0)->whereColumn('available_qty','>','lock_qty');
                                })->whereOr('allow_zero_stock_sale','=',1);
                                break;
                            case 'delivery':
                                break;
                        }
                    })
                    ->whereFindInSet('wid',$value['wid']);
            } else {
                $Inventory->union(function ($query) use($value,$where,$field,$action) {
                    switch ($action) {
                        case 'purchase':
                           $query->table('db_inventory')->where($where)->where(function ($query) {
                               $query->where(function ($query) {
                                   $query->where('available_qty','>',0)->whereColumn('available_qty','>','lock_qty');
                               })->whereOr('allow_zero_stock_sale','=',1);
                            })->field($field)->whereFindInSet('wid',$value['wid']);
                            break;
                        case 'delivery':
                           $query->table('db_inventory')->where($where)->field($field)->whereFindInSet('wid',$value['wid']);
                            break;
                    }
                });
            }
        }

        $inventory = $Inventory->select();


//        echo Db::getlastSql();
//        die;

        if  ( !$inventory ) {
            return Basic::data(1,'未找到库存信息');
        }

        $inventoryData = $inventory->toArray();

        /*  库存分组处理 */
        $groupedArray = [];
        foreach ($inventoryData as $item) {

            $key = implode('_', [
                $item['productid'],
                $item['wid'],
                $item['arrival_date'],
                $item['is_futures']
            ]);

            if (!isset($groupedArray[$key])) {
                $groupedArray[$key] = [
                    'productid' => $item['productid'],
                    'wid' => $item['wid'],
                    'arrival_date' => $item['arrival_date'],
                    'is_futures' => $item['is_futures'],
                    'pay_quantity' => $pay_quantity[$key],
                    'items' => []
                ];
            }

            unset($item['productid']);
            unset($item['wid']);
            unset($item['arrival_date']);
            unset($item['is_futures']);
            $groupedArray[$key]['items'][] = $item;
        }

        $data = array_values($groupedArray);


        /* 库存分组排序 & 同一个库存合并 */
        foreach ($data as &$value) {

            if ( count($value['items']) == 0 ) {
                return Basic::data(1,'库存数据错误');
            }

            /* 去除以售卖完的商品 */
            foreach ($value['items'] as $k => $v) {
                $value['items'][$k]['quantity'] = 0;
                if ( $v['allow_zero_stock_sale'] == 1 ) {
                    continue;
                }
                if ( $v['available_qty'] < $v['lock_qty'] ) {
                    unset($value['items'][$k]);
                }  else {
                    $quantity = $v['available_qty'] - $v['lock_qty'];
                    $value['items'][$k]['quantity'] = $quantity;
                }
            }


            /* 排序处理 */
            switch ($action) {
                case 'purchase':
                    usort($value['items'], function($a, $b) use ($action) {
                        $result = $a['allow_zero_stock_sale'] <=> $b['allow_zero_stock_sale'];
                        if ($result === 0) {
                            $result = $a['id'] <=> $b['id'];
                        }
                        return $result;
                    });
                    break;
                case 'delivery':
                    usort($value['items'], function($a, $b) {
                        $isSaleCompare = $b['is_sale'] <=> $a['is_sale'];
                        if ($isSaleCompare !== 0) {
                            return $isSaleCompare;
                        }
                        return $a['id'] <=> $b['id'];
                    });
                    break;
            }
        }

        /* 判断库存 */
        if( count($condition) != count($data) ) {
            return Basic::data(1,'库存不足');
        }

        switch($action) {
            case 'purchase':

                /*  下单 分配库存 */
                $actualData = [];
                foreach ($data as $key => &$value) {

                    $pay_quantity = (int)$value['pay_quantity'];
                    $available_stock = 0;
                    $allow_zero_stock_sale = 0;


                    foreach ($value['items'] as  $k => $v) {

                        if ( $pay_quantity <= 0 ) {
                            break;
                        }

                        if ( $v['allow_zero_stock_sale'] == 0 ) {
                            $available_stock += $v['quantity'];
                            if ( $pay_quantity >= $v['quantity'] ) {
                                $v['pay_quantity'] = $v['quantity'];
                                $pay_quantity -= $v['quantity'];
                            } else {
                                $v['pay_quantity'] = $pay_quantity;
                                $pay_quantity = 0;
                            }
                            $actualData[$k] = $v;

                        }else {
                            $allow_zero_stock_sale = 1;
                            $v['pay_quantity'] = $pay_quantity;
                            $pay_quantity = 0;
                            $actualData[$k] = $v;
                            break;
                        }
                    }

                    $value['items'] = $actualData;


                    /* 判断库存 */
                    if ( count($value['items']) == 0 ) {
                        return Basic::data(1,'未找到有效库存');
                    }

                    /* 库存不足 */
                    if ( $available_stock < (int)$value['pay_quantity'] && $allow_zero_stock_sale == 0) {
                        $value['exceptionstatus'] = 1;
                    } else {
                        $value['exceptionstatus'] =  null;
                    }

                    /* 超卖处理 */
                    if ( $pay_quantity == 0 ) {
                        $value['exceed_quantity'] = 0;
                    } else {
                        $value['exceed_quantity'] = $pay_quantity;
                    }

                    /* 库存不足 */
                    if ( $pay_quantity == 0 ) {
                        $value['insufficient_inventory'] = 0;
                    } else {
                        $value['insufficient_inventory'] = 1;
                    }
                }

                break;
            case 'delivery':
                /*  下单 分配库存 */
                $actualData = [];
                foreach ($data as $key => &$value) {
                    $pay_quantity = (int)$value['pay_quantity'];
                    foreach ($value['items'] as  $k => $v) {

                        if ( $pay_quantity <= 0 ) {
                            break;
                        }

                        if ( $pay_quantity >= $v['quantity'] ) {
                            $v['pay_quantity'] = $v['quantity'];
                            $pay_quantity -= $v['quantity'];
                        } else {
                            $v['pay_quantity'] = $pay_quantity;
                            $pay_quantity = 0;
                        }
                        $actualData[$k] = $v;

                    }

                    $value['items'] = $actualData;

                    /* 判断库存 */
                    if ( count($value['items']) == 0 ) {
                        return Basic::data(1,'未找到有效库存');
                    }
                }
                break;
            default:
                return Basic::data(1,' Action 方法错误');
        }

        return Basic::data(0,'ok',$data);

    }
}
